#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
自动配置Cloudflare Tunnel用于跨网络权限管理
"""

import os
import sys
import requests
import subprocess
import time
import socket
import json

def check_server_running():
    """检查权限管理服务器是否运行"""
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(2)
        result = sock.connect_ex(('localhost', 8080))
        sock.close()
        return result == 0
    except:
        return False

def download_cloudflared():
    """下载cloudflared"""
    url = "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe"
    
    print("📥 正在下载 cloudflared...")
    print(f"🔗 下载地址: {url}")
    
    try:
        response = requests.get(url, stream=True, timeout=30)
        response.raise_for_status()
        
        total_size = int(response.headers.get('content-length', 0))
        
        with open('cloudflared.exe', 'wb') as f:
            downloaded = 0
            for chunk in response.iter_content(chunk_size=8192):
                if chunk:
                    f.write(chunk)
                    downloaded += len(chunk)
                    if total_size > 0:
                        percent = (downloaded / total_size) * 100
                        print(f"\r📊 下载进度: {percent:.1f}% ({downloaded}/{total_size} bytes)", end='')
        
        print("\n✅ cloudflared 下载完成")
        return True
        
    except requests.RequestException as e:
        print(f"\n❌ 下载失败: {e}")
        return False
    except Exception as e:
        print(f"\n❌ 下载异常: {e}")
        return False

def test_cloudflared():
    """测试cloudflared是否可用"""
    try:
        result = subprocess.run(['cloudflared.exe', '--version'], 
                              capture_output=True, text=True, timeout=10)
        if result.returncode == 0:
            print(f"✅ cloudflared 版本: {result.stdout.strip()}")
            return True
        else:
            print(f"❌ cloudflared 测试失败: {result.stderr}")
            return False
    except Exception as e:
        print(f"❌ cloudflared 测试异常: {e}")
        return False

def start_tunnel():
    """启动Cloudflare隧道"""
    print("\n🚀 启动Cloudflare隧道...")
    print("⏳ 正在创建隧道连接...")
    
    try:
        # 启动隧道进程
        process = subprocess.Popen([
            'cloudflared.exe', 'tunnel', '--url', 'localhost:8080'
        ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        
        # 等待隧道启动并获取URL
        tunnel_url = None
        start_time = time.time()
        
        print("🔍 等待获取公网地址...")
        
        while time.time() - start_time < 60:  # 最多等待60秒
            if process.poll() is not None:
                print("❌ 隧道进程意外退出")
                return None, None
            
            # 检查stderr输出获取URL
            try:
                line = process.stderr.readline()
                if line:
                    print(f"📊 隧道状态: {line.strip()}")
                    
                    # 查找隧道URL
                    if 'https://' in line and 'trycloudflare.com' in line:
                        import re
                        url_match = re.search(r'https://[a-zA-Z0-9-]+\.trycloudflare\.com', line)
                        if url_match:
                            tunnel_url = url_match.group(0)
                            print(f"\n🎉 隧道地址获取成功: {tunnel_url}")
                            break
            except:
                pass
            
            time.sleep(1)
        
        if tunnel_url:
            return process, tunnel_url
        else:
            print("❌ 超时未获取到隧道地址")
            process.terminate()
            return None, None
            
    except Exception as e:
        print(f"❌ 启动隧道失败: {e}")
        return None, None

def update_android_config(tunnel_url):
    """更新Android配置"""
    print(f"\n📱 更新Android配置: {tunnel_url}")
    
    websocket_file = "app/src/main/java/com/example/myapplication/realtime/WebSocketManager.kt"
    
    if not os.path.exists(websocket_file):
        print("❌ WebSocketManager.kt 文件不存在")
        return False
    
    try:
        with open(websocket_file, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # 转换为WebSocket URL
        ws_url = tunnel_url.replace('https://', 'wss://')
        
        # 更新配置
        import re
        
        # 查找并替换PUBLIC_SERVER_URL
        pattern = r'(private const val PUBLIC_SERVER_URL = ")[^"]*(")'
        replacement = f'\\g<1>{ws_url}\\g<2>'
        
        if 'PUBLIC_SERVER_URL' in content:
            content = re.sub(pattern, replacement, content)
        else:
            # 添加新配置
            content = content.replace(
                'class WebSocketManager',
                f'class WebSocketManager'
            )
            content = content.replace(
                'private val isConnected = AtomicBoolean(false)',
                f'private const val PUBLIC_SERVER_URL = "{ws_url}"\n    private val isConnected = AtomicBoolean(false)'
            )
        
        with open(websocket_file, 'w', encoding='utf-8') as f:
            f.write(content)
        
        print(f"✅ Android配置已更新: {ws_url}")
        return True
        
    except Exception as e:
        print(f"❌ Android配置更新失败: {e}")
        return False

def create_monitoring_script(process, tunnel_url):
    """创建监控脚本"""
    monitor_script = f'''@echo off
chcp 65001 >nul
title 权限管理系统 - Cloudflare Tunnel 监控
color 0A

echo.
echo ========================================================
echo     基于权限的患者管理系统 - Cloudflare Tunnel
echo ========================================================
echo.
echo 🌐 隧道地址: {tunnel_url}
echo 📱 Android WebSocket: {tunnel_url.replace('https://', 'wss://')}
echo 🖥️  本地服务器: http://localhost:8080
echo.
echo 📊 状态监控中...
echo 💡 保持此窗口打开以维持隧道连接
echo ⏹️  按 Ctrl+C 停止隧道
echo.

:monitor
timeout /t 10 >nul
echo [%date% %time%] 隧道运行正常 - {tunnel_url}
goto monitor
'''
    
    with open('monitor_tunnel.bat', 'w', encoding='utf-8') as f:
        f.write(monitor_script)
    
    print("✅ 监控脚本已创建: monitor_tunnel.bat")

def test_tunnel_connection(tunnel_url):
    """测试隧道连接"""
    print(f"\n🧪 测试隧道连接: {tunnel_url}")
    
    try:
        import asyncio
        import websockets
        
        async def test_connection():
            ws_url = tunnel_url.replace('https://', 'wss://')
            try:
                async with websockets.connect(ws_url, timeout=10) as websocket:
                    # 等待连接确认
                    response = await websocket.recv()
                    data = json.loads(response)
                    
                    if data.get('type') == 'CONNECTION_ACK':
                        print("✅ 隧道连接测试成功！")
                        print(f"📊 服务器版本: {data.get('data', {}).get('server_version')}")
                        return True
                    else:
                        print("⚠️ 连接响应异常")
                        return False
            except Exception as e:
                print(f"❌ 隧道连接测试失败: {e}")
                return False
        
        return asyncio.run(test_connection())
        
    except ImportError:
        print("⚠️ 跳过连接测试 (缺少websockets库)")
        return True
    except Exception as e:
        print(f"❌ 连接测试异常: {e}")
        return False

def main():
    """主函数"""
    print("🚀 自动配置Cloudflare Tunnel")
    print("🎯 用于基于权限的跨网络患者管理系统")
    print("=" * 60)
    
    # 检查权限管理服务器
    if not check_server_running():
        print("❌ 权限管理服务器未运行")
        print("💡 请先启动: python complete_permission_server.py")
        start = input("\n是否现在启动服务器? (y/N): ").strip().lower()
        if start in ['y', 'yes']:
            print("🚀 启动权限管理服务器...")
            subprocess.Popen([sys.executable, 'complete_permission_server.py'])
            time.sleep(5)
            
            if check_server_running():
                print("✅ 服务器启动成功")
            else:
                print("❌ 服务器启动失败")
                return
        else:
            return
    else:
        print("✅ 权限管理服务器运行正常")
    
    # 检查cloudflared
    if not os.path.exists('cloudflared.exe'):
        print("\n📥 cloudflared 不存在，开始下载...")
        if not download_cloudflared():
            print("❌ 下载失败，请手动下载")
            print("🔗 下载地址: https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe")
            return
    else:
        print("✅ 找到 cloudflared.exe")
    
    # 测试cloudflared
    if not test_cloudflared():
        print("❌ cloudflared 不可用")
        return
    
    # 启动隧道
    process, tunnel_url = start_tunnel()
    
    if not tunnel_url:
        print("❌ 隧道启动失败")
        return
    
    # 更新Android配置
    if update_android_config(tunnel_url):
        print("✅ Android配置更新成功")
    else:
        print("⚠️ Android配置更新失败")
    
    # 测试隧道连接
    if test_tunnel_connection(tunnel_url):
        print("✅ 隧道连接验证成功")
    else:
        print("⚠️ 隧道连接验证失败")
    
    # 创建监控脚本
    create_monitoring_script(process, tunnel_url)
    
    # 显示配置完成信息
    print("\n" + "=" * 60)
    print("🎉 Cloudflare Tunnel 配置完成！")
    print(f"\n🌐 公网访问地址: {tunnel_url}")
    print(f"📱 Android WebSocket: {tunnel_url.replace('https://', 'wss://')}")
    print(f"🖥️  本地服务器: http://localhost:8080")
    
    print("\n📝 下一步:")
    print("1. 重新编译APK: gradlew assembleRelease")
    print("2. 安装到设备: adb install -r app/build/outputs/apk/release/app-release.apk")
    print("3. 使用测试账号登录:")
    print("   • 超级管理员: admin / admin123")
    print("   • 内科主任: dept_admin_neike / dept123")
    print("   • 内科医生: user_neike1 / user123")
    print("   • 外科医生: user_waike1 / user123")
    
    print("\n🧪 测试场景:")
    print("• 内科医生添加患者 → 内科主任实时收到通知")
    print("• 外科医生添加患者 → 内科主任看不到")
    print("• 超级管理员能看到所有患者信息")
    
    print(f"\n💡 保持隧道运行:")
    print("• 此进程必须保持运行")
    print("• 或运行监控脚本: monitor_tunnel.bat")
    
    # 保持隧道运行
    try:
        print("\n⏳ 隧道运行中... (按 Ctrl+C 停止)")
        while True:
            if process.poll() is not None:
                print("\n❌ 隧道进程意外退出")
                break
            time.sleep(10)
            print(f"[{time.strftime('%H:%M:%S')}] 隧道运行正常")
    except KeyboardInterrupt:
        print("\n⏹️ 用户停止隧道")
    finally:
        if process and process.poll() is None:
            process.terminate()
            print("✅ 隧道进程已停止")

if __name__ == "__main__":
    try:
        main()
    except Exception as e:
        print(f"\n❌ 配置失败: {e}")
        input("按回车键退出...") 